using System;
using System.Drawing;
using System.Reflection;
using System.Resources;

namespace NewTcGui
{
	public class TcPassFrame: wx.Frame
	{
		private enum Id
		{
			passwordTextCtrl,
			configMenuItem,
			exitMenuItem,
			umountMenuItem,
			statusBar
		}
		
		//data members
		private string password;
		private TcConfig cfg;
		private TcMounter mounter;
		
		
		//controls
		private wx.TextCtrl passwordTextCtrl;
		private wx.Button okButton;
		private wx.Button cancelButton;
		private wx.StatusBar statusBar;
		private TcAboutDialog aboutDialog;
		
		public TcPassFrame(wx.Window parent, int id, string title, Point pos, Size size, uint style):
			base(parent, id, title, pos, size, style)
		{
			cfg = new TcConfig();
		
			//create menu and status bar
			CreateMenu();
			//create controls and place them on position
			CreateControls();
			//set same controls poperties
			SetControlsProperties();
						
			EVT_BUTTON(wx.Window.wxID_OK, new wx.EventListener(OnOkButtonClicked));
			EVT_BUTTON(wx.Window.wxID_CANCEL, new wx.EventListener(OnCancelButtonClicked));
			EVT_MENU(wx.Window.wxID_ABOUT, new wx.EventListener(OnAboutMenuClicked));
			EVT_MENU((int) Id.configMenuItem, new wx.EventListener(OnConfigMenuClicked));
			EVT_MENU((int) Id.umountMenuItem, new wx.EventListener(OnUmountMenuClicked));
			EVT_MENU((int) Id.exitMenuItem, new wx.EventListener(OnExitMenuClicked));
			EVT_KEY_DOWN(new wx.EventListener(OnEscKey));
//			EVT_CLOSING(new wx.EventListener(OnClose));
			this.Closing += new wx.EventListener(OnClosing);
		}
		
		private void CreateControls()
		{
			//general window sizer
			wx.BoxSizer topSizer = new wx.BoxSizer(wx.Orientation.wxVERTICAL);
			
			//"real" window sizer, which adds some space between borders
			wx.BoxSizer boxSizer = new wx.BoxSizer(wx.Orientation.wxVERTICAL);
			topSizer.Add(boxSizer, 1, wx.Stretch.wxEXPAND|wx.Direction.wxALL|
			             wx.Direction.wxRIGHT|wx.Direction.wxTOP, 10);
			
			//top spacer
			boxSizer.Add(5, 5, 0, wx.Direction.wxALL|wx.Alignment.wxALIGN_CENTER_HORIZONTAL|
			             wx.Alignment.wxALIGN_CENTER_VERTICAL, 5);
			
			
			//password entry field
			passwordTextCtrl = new wx.TextCtrl(this, (int) Id.passwordTextCtrl, "", 
			                                               wx.Window.wxDefaultPosition, new Size(150, 24),
			                                               wx.TextCtrl.wxTE_PASSWORD);
			boxSizer.Add(passwordTextCtrl, 0, wx.Stretch.wxEXPAND|wx.Direction.wxALL, 5);
			
			//midle spacer
			boxSizer.Add(5, 5, 0, wx.Direction.wxALL|wx.Alignment.wxALIGN_CENTER_HORIZONTAL|
			             wx.Alignment.wxALIGN_CENTER_VERTICAL, 5);
			
			//sizer for buttons
			wx.BoxSizer buttonsSizer = new wx.BoxSizer(wx.Orientation.wxHORIZONTAL);
			boxSizer.Add(buttonsSizer, 0, wx.Stretch.wxEXPAND|wx.Direction.wxALL, 5);
			
			//cancel button
			cancelButton = new wx.Button(this, wx.Window.wxID_CANCEL, "&Cancel");
			buttonsSizer.Add(cancelButton, 1, wx.Alignment.wxALIGN_CENTER_VERTICAL|
			                 wx.Direction.wxALL, 5);

			//spacer between butons
			buttonsSizer.Add(5, 5, 0, wx.Alignment.wxALIGN_CENTER_VERTICAL, 0);

			//ok button
			okButton = new wx.Button(this, wx.Window.wxID_OK, "&OK");
			
			buttonsSizer.Add(okButton, 1, wx.Direction.wxALL|
			                 wx.Alignment.wxALIGN_CENTER_VERTICAL, 5);

			
			this.SetSizer(topSizer);
			topSizer.Fit(this);
			topSizer.SetSizeHints(this);
			
		}
		
		private void SetControlsProperties()
		{
			passwordTextCtrl.SetFocus();
			okButton.ToolTip = "Mount volume/volumes";
			okButton.SetDefault();
			cancelButton.ToolTip = "Exit without mounting";

			//read icon image from resource embedded in assembly
			byte[] byteImg = TcGuiApp.GetBytesFromAssembly("face-devilish.png", "Resources");
			wx.Image img = new wx.Image(byteImg, wx.BitmapType.wxBITMAP_TYPE_PNG);
			wx.Bitmap bmp = new wx.Bitmap(img);
			wx.Icon icon = new wx.Icon();
			icon.CopyFromBitmap(bmp);
			this.Icon = icon;
			

			if (cfg.ReadConfigFile()) 
			{
				if (cfg.mountPoints.Count > 0) 
					this.StatusText = String.Format("Input password for: {0}", cfg.mountPoints[0].dev);
				else
					this.StatusText = "You don't have any mount points!";
			}
			else
			{
				this.StatusText = "You have't generated config file yet!";
			}
		}
		
		private void CreateMenu()
		{
			wx.Menu fileMenu = new wx.Menu();
			wx.Menu toolsMenu = new wx.Menu();
			wx.Menu helpMenu = new wx.Menu();
						
			fileMenu.Append((int) Id.exitMenuItem, "&Exit\tCtrl+Q", "Close the application");
			
			toolsMenu.Append((int) Id.configMenuItem, "&Configuration", "Open configuration window");
			toolsMenu.Append((int) Id.umountMenuItem, "&Umount all drives\tCtrl+U", "Umount all mounted volumes");
			
			helpMenu.Append(wx.Window.wxID_ABOUT, "&About", "Show information about application and author");
			
			wx.MenuBar menuBar = new wx.MenuBar();
			menuBar.Append(fileMenu, "&File");
			menuBar.Append(toolsMenu, "&Tools");
			menuBar.Append(helpMenu, "&Help");
			this.MenuBar = menuBar;
			
			statusBar = new wx.StatusBar(this, -1, 1);
			this.StatusBar = statusBar;

		}
		
		protected void OnOkButtonClicked(object sender, wx.Event evt)
		{
			wx.BusyCursor busy = new wx.BusyCursor();
			
			if (CheckConfigFile(true)) 
			{
				System.Console.WriteLine("Config file ok!");
				if(cfg.mountPoints.Count > 0)
				{
					System.Console.WriteLine("There are {0} volumes on the list", cfg.mountPoints.Count);
					if(passwordTextCtrl.Value.Trim() == String.Empty)
					{
						busy.Dispose();
						return;
					}
					else
					{
						password = passwordTextCtrl.Value.Trim();
						mounter = new TcMounter(cfg.tcPath);
						System.Console.WriteLine("Path to truecrypt exec is: {0}", cfg.tcPath);
						TcConfig tmpCfg= new TcConfig();
						tmpCfg.ReadConfigFile();
						System.Console.WriteLine("Using the same password is set to: {0}", cfg.samePasswd.ToString());
						
						if (cfg.samePasswd) 
						{
							foreach(MountPoint mp in tmpCfg.mountPoints)
							{
								
								System.Console.WriteLine("Mounting: {0}{1} {2}...", mp.dev, mp.dir, mp.parameters);
								MountHelper mh = mounter.Mount(mp, password);
								
								//if mounting fail
								if (!mh.succeed) 
								{
									
									if (mh.wrongPasswd) 
									{
										System.Console.WriteLine("Wrong password");
										string msg = mh.msg + "\nWould you like to try it again?";
										wx.MessageDialog badPassDlg = new wx.MessageDialog(this,
										      msg, "Incorect password", wx.MessageDialog.wxICON_QUESTION|
										wx.MessageDialog.wxOK|wx.MessageDialog.wxCANCEL);

										int res = badPassDlg.ShowModal();
										
										switch(res)
										{
											case wx.MessageDialog.wxID_OK:
												passwordTextCtrl.Value = "";
												busy.Dispose();
												return;
											
											case wx.MessageDialog.wxID_CANCEL:
												passwordTextCtrl.Value = "";
												cfg.mountPoints.Remove(mp);
												if (cfg.mountPoints.Count == 0) 
												{											
													this.Close();
													System.Console.WriteLine("There is nothing on the list, exiting...");
												}
												break;
										}			
									}
									else
									{
										System.Console.WriteLine("Other error");
										string msg = mh.msg + "\nMaybe you should check the configuration";
										wx.MessageDialog errorDlg = new wx.MessageDialog(this,
										      msg, "Unable to mount volume", wx.MessageDialog.wxICON_ERROR);
										errorDlg.ShowModal();
										
										//remove current volume from the list and clean text ctrl
										cfg.mountPoints.Remove(mp);
										passwordTextCtrl.Value = String.Empty;
										//check if there is no need to mount other volumes
										if (cfg.mountPoints.Count == 0) 
										{
											System.Console.WriteLine("There is nothing on the list, exiting...");
											this.Close();
										}
									}
								}
								else
								{
									//volume mounted correctly so remove it from the list
									System.Console.WriteLine("Volume mounted correctly");
									cfg.mountPoints.Remove(mp);
									passwordTextCtrl.Value = String.Empty;
									if (cfg.mountPoints.Count == 0) 
									{
										System.Console.WriteLine("There is nothing on the list, exiting...");
										this.Close();
									}
								}
							}
						}
						else // if samePasswd is set to false
						{
							//take first on the list
							MountPoint mp = cfg.mountPoints[0];
							System.Console.WriteLine("Mounting: {0}{1} {2}...", mp.dev, mp.dir, mp.parameters);
							MountHelper mh = mounter.Mount(mp, password);
							
							if (!mh.succeed) 
							{
								if (mh.wrongPasswd) 
								{
									System.Console.WriteLine("Wrong password");
									string msg = mh.msg + "\nWould you like to try it again?";
									wx.MessageDialog badPassDlg = new wx.MessageDialog(this,
									      msg, "Incorect password", wx.MessageDialog.wxICON_QUESTION|
									wx.MessageDialog.wxOK|wx.MessageDialog.wxCANCEL);

									int res = badPassDlg.ShowModal();
									
									switch(res)
									{
										case wx.MessageDialog.wxID_OK:
											passwordTextCtrl.Value = "";
											busy.Dispose();
											return;
										
										case wx.MessageDialog.wxID_CANCEL:
											passwordTextCtrl.Value = "";
											cfg.mountPoints.Remove(mp);
											if (cfg.mountPoints.Count == 0) 
											{
												System.Console.WriteLine("There is nothing on the list, exiting...");
												this.Close();
											}
											else
												StatusText = String.Format("Input password for: {0}", 
											                           cfg.mountPoints[0].dev);
											break;
									}			
								}
								else
								{
									System.Console.WriteLine("Other error");
									string msg = mh.msg + "\nMaybe you should check the configuration";
									wx.MessageDialog errorDlg = new wx.MessageDialog(this,
									      msg, "Unable to mount volume", wx.MessageDialog.wxICON_ERROR);
									errorDlg.ShowModal();
									
									//remove current volume from the list and clean text ctrl
									cfg.mountPoints.Remove(mp);
									passwordTextCtrl.Value = String.Empty;
									//check if there is no need to mount other volumes
									if (cfg.mountPoints.Count == 0) 
									{
										System.Console.WriteLine("There is nothing on the list, exiting...");
										this.Close();
									}
									else
										StatusText = String.Format("Input password for: {0}", 
										                           cfg.mountPoints[0].dev);
								}
							}
							else
							{
								//volume mounted correctly so remove it from the list
								System.Console.WriteLine("Volume mounted correctly");
								cfg.mountPoints.Remove(mp);
								passwordTextCtrl.Value = String.Empty;
								if (cfg.mountPoints.Count == 0) 
								{
									System.Console.WriteLine("There is nothing on the list, exiting...");
									this.Close();
								}
								else
									StatusText = String.Format("Input password for: {0}", 
										                           cfg.mountPoints[0].dev);
							}
						}
					}
				}
				else
				{
					System.Console.WriteLine("There are none volumes on the list");
					this.Close();
				}
			}

			busy.Dispose();
		}
		
		protected void OnCancelButtonClicked(object sender, wx.Event evt)
		{
			this.SetStatusText("TrueCrypt Mounting GUI Jacek Trubłajewicz <gothic@os.pl>");
		}
		
		protected void OnAboutMenuClicked(object sender, wx.Event evt)
		{
			if (aboutDialog == null) 
			{
				aboutDialog = new TcAboutDialog(this);
				aboutDialog.Show();
			}
			else
			{
				aboutDialog.Show();
				aboutDialog.Raise();
				
			}
			
			
//			wx.XmlResource.Get().Load("TcAboutDialog.xrc");
//			wx.Dialog dlg = new wx.Dialog();
//			wx.XmlResource.Get().LoadDialog(dlg, this, "aboutDialog");
//			dlg.ShowModal();
		}
		
		protected void OnConfigMenuClicked(object sender, wx.Event evt)
		{
			TcConfigDialog confDlg = new TcConfigDialog(this, -1, "Configuration",
			                                            wx.Window.wxDefaultPosition,
			                                            wx.Window.wxDefaultSize,
			                                            wx.Dialog.wxMINIMIZE_BOX|
			                                            wx.Dialog.wxCLOSE_BOX|
			                                            wx.Dialog.wxMAXIMIZE_BOX|
			                                            wx.Dialog.wxRESIZE_BORDER|
			                                            wx.Dialog.wxSYSTEM_MENU);
			confDlg.ShowModal();
		}
		
		protected void OnUmountMenuClicked(object sender, wx.Event evt)
		{
			TcConfig cfg = new TcConfig();
			if (cfg.ReadConfigFile()) 
			{
				TcMounter mounter = new TcMounter(cfg.tcPath);
				mounter.UmountAll();
				wx.MessageDialog msgDlg = new wx.MessageDialog(this, 
				                                               "All volumes have been umounted", 
				                                               "Umount all volumes",
				                                               wx.MessageDialog.wxICON_INFORMATION);
				msgDlg.ShowModal();
				ReloadConfig();				                                               
			}
			else
			{
				wx.MessageDialog msgDlg = new wx.MessageDialog(this, 
				                                               "Error durning reading config file", 
				                                               "Umount all volumes",
				                                               wx.MessageDialog.wxICON_INFORMATION);
				msgDlg.ShowModal();
			}
			
		}
		
		public void ReloadConfig()
		{
			cfg.ReadConfigFile();
		}
		
		private bool CheckConfigFile(bool showConfDialog)
		{
			TcConfig cfg = new TcConfig();
			bool confOk = cfg.ReadConfigFile();
			
			if (!confOk && showConfDialog) 
			{
				string msg = "You don't have any mount points configured.\nYou will be now transfered to configuration window.";
				wx.MessageDialog dlg = new wx.MessageDialog(this, msg, "No mount point found", 
				                                            wx.MessageDialog.wxICON_EXCLAMATION);
				dlg.Center();
				dlg.ShowModal();
				
				TcConfigDialog confDlg = new TcConfigDialog(this, -1, "Configuration", 
				                                            wx.Window.wxDefaultPosition,
				                                            wx.Window.wxDefaultSize,
				                                            wx.Dialog.wxMINIMIZE_BOX|
				                                            wx.Dialog.wxCLOSE_BOX|
				                                            wx.Dialog.wxMAXIMIZE_BOX|
				                                            wx.Dialog.wxRESIZE_BORDER|
				                                            wx.Dialog.wxSYSTEM_MENU);
				confDlg.Center();
				confDlg.ShowModal();
				
				ReloadConfig();
				//this is dangerous
				return true;
			}
			
			if (!confOk && !showConfDialog)
				return false;
			
			return true;
		}
		
		protected void OnExitMenuClicked(object sender, wx.Event evt)
		{
			this.Close();
		}
		
		protected void OnEscKey(object sender, wx.Event evt)
		{
			wx.KeyEvent key = (wx.KeyEvent) evt;
			if (key.KeyCode == (int) wx.KeyCode.WXK_ESCAPE) 
			{
				this.Close();
			}
		}
		
		protected void OnClosing(object sender, wx.Event evt)
		{
//			trayIcon.Dispose();
			evt.Skip();
		}
		
		
	}
}

